// smtest.c++
// Sample server which accepts and prints out
// strings, floats, and ints.
// Command line options for SIGIO and UDP.

#include <iostream>
#include <signal.h>
#include <stdlib.h>

#include "SocketMan.h"

const int port = 14159;
SocketMan *sm;
SocketBuf *sbptr;

void
readDataHandler(int)
{
	cerr << "In readDataHandler" << endl;

	// If we're running linux, this may help to prevent ourselves getting killed
	// Better answer: don't use SIGIO.

	sm->rewindSockets();

	while (sm->nextSocket())
	{
		if ((sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET_LENGTH) ||
			(sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET_DATA_TYPE) ||
			(sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET))
		{
			sbptr = sm->recoverFromReadError();
		}
		else
		{
			sbptr = sm->readWithPollAndTimeout();
		}

		if (sbptr)
		{
			if (sbptr->num_bytes < 1000)
			{
				cerr << "READ SUCCEEDED" << endl;

				switch (sbptr->type)
				{
				case SOCKET_CHAR:
					{
						cerr << "The secret message of the day is: " << (char *)sbptr->buf << endl;
						break;
					}

				case SOCKET_INT:
					{
						int counter;

						cerr << "Integer vector received. Numbers: ";

						for(counter = 0; counter < sbptr->num_bytes; counter += sizeof(int))
						{
							cerr << *((int *) (sbptr->buf + counter )) << " ";
						}

						cerr << endl;
						break;
					}

				case SOCKET_FLOAT:
					{
						int counter;

						cerr << "Float vector received. Numbers: ";

						for(counter = 0; counter < sbptr->num_bytes; counter += sizeof(float))
						{
							cerr << *((float *) (sbptr->buf + counter )) << " ";
						}

						cerr << endl;
						break;
					}
				}
			}
			else
			{
				if (sbptr->num_bytes_successful == 1048576)
					cerr << "BIG READ COMPLETED" << endl;
				else
					cerr << "**BIG READ FAILED**: num_bytes_successful == " << sbptr->num_bytes_successful << endl;
			}
			delete sbptr;
		}
	}
#ifdef linux
	signal(SIGIO, readDataHandler);
#endif

#ifdef __hpux
	signal(SIGIO, readDataHandler);
#endif
}

int main(int argc, char **argv)
{
	int use_sigio;
	int use_udp;

	if (argc != 2)
	{
		cerr << "usage: smtest <use SIGIO: [0,1]> <use UDP: [0,1]>" << endl;
		exit(1);
	}
	else
	{
		use_sigio = atoi(argv[0]);
		use_udp = atoi(argv[1]);
	}

	sm = new SocketMan(port, 0, 0, 0, 500000, 0, 0, use_sigio, 1, use_udp);

	if (use_sigio)
	{
#ifndef WIN32
		signal(SIGIO, readDataHandler);
		while (1)
			sm->acceptConnectionWithPoll();
#else
		cerr << "SIGIO not supported on Windows, sorry" << endl;
		exit(1);
#endif
	}
	else
	{
		int counter = 0;

		while (1)
		{
			sm->acceptConnectionWithPoll();

			sm->rewindSockets();

			while (sm->nextSocket())
			{
				if ((sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET_LENGTH) ||
					(sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET_DATA_TYPE) ||
					(sm->getLastMessage() == SocketMan::ERR_TIMEOUT_READING_PACKET))
				{
					sbptr = sm->recoverFromReadError();
				}
				else
				{
					sbptr = sm->readWithPollAndTimeout();
				}

				if (sbptr)
				{
					if (sbptr->num_bytes < 1000)
					{
						cerr << "READ SUCCEEDED" << endl;

						switch (sbptr->type)
						{
						case SOCKET_CHAR:
							{
								cerr << "The secret message of the day is: " << (char *)sbptr->buf << endl;
								break;
							}

						case SOCKET_INT:
							{
								int counter;

								cerr << "Integer vector received. Numbers: ";

								for(counter = 0; counter < sbptr->num_bytes; counter += sizeof(int))
								{
									cerr << *((int *) (sbptr->buf + counter )) << " ";
								}

								cerr << endl;
								break;
							}

						case SOCKET_FLOAT:
							{
								int counter;

								cerr << "Float vector received. Numbers: ";

								for(counter = 0; counter < sbptr->num_bytes; counter += sizeof(float))
								{
									cerr << *((float *) (sbptr->buf + counter )) << " ";
								}

								cerr << endl;
								break;
							}
						}
					}
					else
					{
						if (sbptr->num_bytes_successful == 1048576)
							cerr << "BIG READ COMPLETED" << endl;
						else
							cerr << "**BIG READ FAILED**: num_bytes_successful == " << sbptr->num_bytes_successful << endl;
					}
					delete sbptr;
				}
			}
		}
	}
	return 0;
}
